package com.xxxx.server.service.impl;


import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxxx.server.mapper.AdminMapper;
import com.xxxx.server.mapper.AdminRoleMapper;
import com.xxxx.server.mapper.RoleMapper;
import com.xxxx.server.pojo.Admin;
import com.xxxx.server.pojo.AdminRole;
import com.xxxx.server.pojo.RespBean;
import com.xxxx.server.pojo.Role;
import com.xxxx.server.service.IAdminService;
import com.xxxx.server.service.IFileUploadService;
import com.xxxx.server.utils.AssertUtil;
import com.xxxx.server.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zhoubin
 * @since 2020-10-15
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements IAdminService {

	@Autowired
	private UserDetailsService userDetailsService;
	@Autowired
	private PasswordEncoder passwordEncoder;
	@Autowired
	private JwtUtils jwtUtils;
	@Value("${jwt.tokenHead}")
	private String tokenHead;
	@Resource
	private AdminMapper adminMapper;
	@Resource
	private RoleMapper roleMapper;
	@Resource
	private AdminRoleMapper adminRoleMapper;
	@Resource
	private IFileUploadService fileUploadService;
	@Resource
	private RedisTemplate redisTemplate;

	private  final String ADMIN_ROLE_ZH="系统管理员";//管理员角色名
	/**
	 * 登录
	 * @param username
	 * @param password
	 * @return
	 */
	@Override
	public RespBean login(String username, String password) {
		UserDetails userDetails = userDetailsService.loadUserByUsername(username);
		//判断用户是否存在
		if (null==userDetails||!passwordEncoder.matches(password,userDetails.getPassword())){
			throw new UsernameNotFoundException("用户名或密码不正确");
		}
		//判断用户是否启用
		if (!userDetails.isEnabled()){
			return RespBean.error("用户尚未启用，请联系管理员");
		}
		//将当前用户对象存入SpringSecurity全局上下文，方便其他方法使用
		UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails,
				null, userDetails.getAuthorities());
		SecurityContextHolder.getContext().setAuthentication(authenticationToken);
		//生成token并返回
		String token = jwtUtils.generatorToken(userDetails);
		Map<String,Object> tokenMap = new HashMap<>();
		tokenMap.put("tokenHead",tokenHead);
		tokenMap.put("token",token);
		return RespBean.success("登录成功",tokenMap);
	}

	@Override
	public RespBean login(String username, String password, String code, HttpServletRequest request) {
		//获取验证码内容
		String captcha = (String) request.getSession().getAttribute("captcha");
		//忽略大小写进行比对
		if (StringUtils.isBlank(code) || !captcha.equals(code)) {
			return RespBean.error("验证码填写错误！");
		}

		UserDetails userDetails = userDetailsService.loadUserByUsername(username);
		if (null == userDetails || !passwordEncoder.matches(password,
				userDetails.getPassword())) {
			return RespBean.error("用户名或密码不正确!");
		}
		if (!userDetails.isEnabled()){
			return RespBean.error("账号被禁用，请联系管理员!");
		}
		UsernamePasswordAuthenticationToken authentication =
				new UsernamePasswordAuthenticationToken(userDetails, null,
						userDetails.getAuthorities());
		SecurityContextHolder.getContext().setAuthentication(authentication);
		String token = jwtUtils.generatorToken(userDetails);
		Map<String, String> tokenMap = new HashMap<>();
		tokenMap.put("token", token);
		tokenMap.put("tokenHead", tokenHead);
		return RespBean.success("登录成功", tokenMap);
	}


	/**
	 * 根据用户名获取用户信息
	 */
	@Override
	public Admin getUserByUsername(String username) {
		Admin admin = adminMapper.selectByUserName(username);
		AssertUtil.isTrue(null == admin,"该用户不存在");
		return admin;
	}


	@Override
	public List<Role> getRoles(Integer id) {
		return roleMapper.getRoles(id);
	}


	/**
	 * 获取所有操作员信息
	 */
	@Override
	public List<Admin> getAdminsByNameLike(String keywords) {
		//模糊查询
		List<Admin> admins = adminMapper.selectByNameLike(keywords);
		//将密码置空
		admins.forEach(t->t.setPassword(null));
		return admins;
	}

	/**
	 * 修改操作员角色
	 * @param adminId
	 * @param rids
	 * @return
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public RespBean updateRolesById(Integer adminId, String rids) {
		//插入数据条数
		int insertCount=0;

		//adminId是否存在
		if (null==adminId){
			return RespBean.error("操作失败，该操作员不存在");
		}

		Admin admin = adminMapper.selectById(adminId);

		//判断操作员是否存在
		if (null==admin){
			return RespBean.error("操作失败，该操作员不存在");
		}

		//不能修改管理员的角色
		//根据adminId查询角色
		List<Role> roleList = roleMapper.getRolesByAdminId(adminId);
		roleList.forEach(t->{
			AssertUtil.isTrue(ADMIN_ROLE_ZH.equals(t.getNameZh()),"您无权修改其他管理员！");
		});

		//如果角色被禁用
		if (!admin.getEnabled()){
			return RespBean.error("角色修改失败，该角色已被禁用");
		}

		//获取该用户下权限的个数
		Integer count = adminRoleMapper.getCountByAdminId(adminId);

		//删除该用户下所有角色
		Integer sum = adminRoleMapper.deleteByAdminId(adminId);
		//如果角色未清空
		AssertUtil.isTrue(count!=sum,"角色修改失败,该账户下角色未清空");

		//如果角色列表不为空
		if (null!=rids && !"".equals(rids)){
			String[] ridsStr = rids.split(",");
			System.out.println("ridsStr:"+ridsStr);
			//新建一个adminRole对象
			AdminRole adminRole = new AdminRole();
			//设置adminId
			adminRole.setAdminId(adminId);
			//遍历权限列表
			for (String rid:ridsStr){
				//设置权限
				adminRole.setRid(Integer.parseInt(rid));
				//保存权限
				adminRoleMapper.insertAdminRole(adminRole);
				insertCount++;
			}
			AssertUtil.isTrue(insertCount<ridsStr.length,"用户角色绑定失败");

		}else {
			//若角色表为空则设置默认权限
			AdminRole adminRole =new AdminRole();
			adminRole.setAdminId(adminId);
			adminRole.setRid(8);
			adminRoleMapper.insertAdminRole(adminRole);
		}
		//删除改角色下的菜单
     	redisTemplate.delete("menu_"+adminId);
		return RespBean.success("角色修改成功");
	}

	/**
	 * 修改操作员启用状态
	 * @param i
	 * @param adminId
	 * @return
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public RespBean updateEnableStatus(int i,Integer adminId) {
		//不能修改管理员的角色
		//根据adminId查询角色
		List<Role> roleList = roleMapper.getRolesByAdminId(adminId);
		roleList.forEach(t->{
			AssertUtil.isTrue(ADMIN_ROLE_ZH.equals(t.getNameZh()),"您无权修改其他管理员！");
		});
		Integer updatedNums = adminMapper.updateEnableStatus(i,adminId);
		AssertUtil.isTrue(updatedNums<1,"操作员状态禁用状态修改失败");
		return RespBean.success("修改成功");
	}

	/**
	 * 根据id删除操作员
	 * @param id
	 * @return
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public RespBean deleteAdminById(Integer id) {
		//不能删除管理员
		List<Role> roleList = roleMapper.getRolesByAdminId(id);
		roleList.forEach(t->{
			AssertUtil.isTrue(ADMIN_ROLE_ZH.equals(t.getNameZh()),"您不能删除管理员！");
		});

		Integer sums =  adminMapper.updateIsActiveById(id);
		AssertUtil.isTrue(sums!=1,"操作员删除失败！");
		return RespBean.success("删除成功");
	}


	/**
	 * 修改个人信息
	 * @param admin
	 * @return
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public RespBean updateAdminInfo(Map<String, Object> admin) {
		AssertUtil.isTrue(null==admin,"信息不能为空");
		//获取待更新的用户信息
		Integer id= (Integer) admin.get("id");
		String name = (String) admin.get("name");
		String phone = (String) admin.get("phone");
		String telephone = (String) admin.get("telephone");
		String address = (String) admin.get("address");

		AssertUtil.isTrue(null==name||"".equals(name),"昵称不能为空");
		AssertUtil.isTrue(null==phone||"".equals(phone),"电话号码不能为空");
		AssertUtil.isTrue(null==telephone||"".equals(telephone),"手机号码不能为空");
		AssertUtil.isTrue(null==address||"".equals(address),"地址不能为空");

		//修改个人信息
		Integer sum = adminMapper.updateAdminInfo(id,name,phone,telephone,address);
		AssertUtil.isTrue(sum!=1,"修改失败");
		return RespBean.success("修改成功");
	}

	/**
	 * 修改密码
	 * @param ruleForm
	 * @return
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public RespBean updatePwdById(Map<String, Object> ruleForm) {
		//ruleForm非空
		AssertUtil.isTrue(null==ruleForm,"密码不能为空");
		//[pass, checkPass, oldPass, adminId]
		String password= (String) ruleForm.get("pass");
		String checkPass = (String) ruleForm.get("checkPass");
		 String oldPass = (String) ruleForm.get("oldPass");
		 Integer adminId= (Integer) ruleForm.get("adminId");
		 AssertUtil.isTrue(null==adminId,"用户id不能为空");
		 AssertUtil.isTrue(null==password||null==checkPass||oldPass==null,"密码不能为空");
		 AssertUtil.isTrue("".equals(password)||"".equals(checkPass)||"".equals(oldPass),"密码不能为空");
		 AssertUtil.isTrue(!password.equals(checkPass),"密码和确认密码不相等");

		AssertUtil.isTrue(password.equals(oldPass),"新密码不能和旧密码相等");
		Admin admin = adminMapper.selectById(adminId);
		AssertUtil.isTrue(null==admin,"该用户不存在");


		AssertUtil.isTrue(!passwordEncoder.matches(oldPass,admin.getPassword()),"原始密码错误");

		//加密新密码
		String encodePwd = passwordEncoder.encode(password);
		//修改密码
		Integer nums = adminMapper.updatePwdById(encodePwd,adminId);
		AssertUtil.isTrue(1!=nums,"密码修改失败");
		return RespBean.success("密码修改成功");
	}

	/**
	 * 修改头像
	 * @param file
	 * @return
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public RespBean changeUserFace(MultipartFile file,Integer id) {
		//上传文件到七牛云
		String url = fileUploadService.fileUpload(file);
		AssertUtil.isTrue(null==url||"".equals(url),"头像上传失败");
		//保存图片的url
		Integer num = adminMapper.uploadUserFaceUrl(url,id);
		AssertUtil.isTrue(num!=1,"图片保存失败");
		return RespBean.success("保存成功");
	}

	/**
	 * 通过关键字获取所有admin
	 * @param data
	 * @return
	 */
    @Override
    public List<Admin> getAllAdmins(String data) {
        return adminMapper.getAllAdmins(((Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId(),data);
    }
}

